/**
 * 
 */
package stubs;

import java.util.ArrayList;

import joint.JointOperator;
import massDistribution.ClassAttributeMap;
import massDistribution.JointMassDistribution;
import massDistribution.MassDistribution;
import core.FrameOfDiscernment;
import engine.ExternalSource;
import engine.RelationshipManager;
import engine.ReputationManager;
import engine.Service;
import engine.TrustMAnager;
import exception.DempsterTotalConflictException;
import exception.JointNotPossibleException;
import exception.MassDistributionNotValidException;
import exceptions.NullSourcesException;

/**
 * This class is a manager for simulate the result obtained using the trust
 * engine.
 * 
 * @author Elisa Costante
 */
public class Simulator {

	private ArrayList<Service> monitoredServices;
	private ArrayList<ExternalSource> allSources;
	/**
	 * @uml.property name="trustConfiguration"
	 * @uml.associationEnd
	 */
	private ClassAttributeMap trustConfiguration;
	/**
	 * @uml.property name="frameOfDiscernment"
	 * @uml.associationEnd
	 */
	private FrameOfDiscernment frameOfDiscernment;

	public Simulator() {

	}

	/**
	 * @return the monitoredServices
	 * @uml.property name="monitoredServices"
	 */
	public ArrayList<Service> getMonitoredServices() {
		return this.monitoredServices;
	}

	/**
	 * @param monitoredServices
	 *            the monitoredServices to set
	 * @uml.property name="monitoredServices"
	 */
	public void setMonitoredServices(ArrayList<Service> monitoredServices) {
		if (monitoredServices != null) {
			this.monitoredServices = new ArrayList<Service>();
			for (Service service : monitoredServices) {
				try {
					this.monitoredServices.add((Service) service.clone());
				} catch (CloneNotSupportedException e) {
					e.printStackTrace();
				}
			}
		}

	}

	/**
	 * @return the allSources
	 * @uml.property name="allSources"
	 */
	public ArrayList<ExternalSource> getAllSources() {
		return this.allSources;
	}

	/**
	 * @param allSources
	 *            the allSources to set
	 * @uml.property name="allSources"
	 */
	public void setAllSources(ArrayList<ExternalSource> allSources) {
		if (allSources != null) {
			this.allSources = new ArrayList<ExternalSource>();

			for (ExternalSource externalSource : allSources) {

				ExternalSource clonedSOurce = new ExternalSource(externalSource
						.getIdentifierName());

				if (externalSource.getMeasuredServices() != null) {
					for (Service service : externalSource.getMeasuredServices()) {
						try {
							clonedSOurce.addMeasuredService((Service) service
									.clone());
						} catch (CloneNotSupportedException e) {
							e.printStackTrace();
						}

					}
				}
				this.allSources.add(clonedSOurce);
			}
		}

	}

	/**
	 * @return the trustConfiguration
	 * @uml.property name="trustConfiguration"
	 */
	public ClassAttributeMap getTrustConfiguration() {
		return this.trustConfiguration;
	}

	/**
	 * @param trustConfiguration
	 *            the trustConfiguration to set
	 * @uml.property name="trustConfiguration"
	 */
	public void setTrustConfiguration(ClassAttributeMap trustConfiguration) {
		this.trustConfiguration = trustConfiguration;
	}

	/**
	 * @return the frameOfDiscernment
	 * @uml.property name="frameOfDiscernment"
	 */
	public FrameOfDiscernment getFrameOfDiscernment() {
		return this.frameOfDiscernment;
	}

	/**
	 * @param frameOfDiscernment
	 *            the frameOfDiscernment to set
	 * @uml.property name="frameOfDiscernment"
	 */
	public void setFrameOfDiscernment(FrameOfDiscernment frameOfDiscernment) {
		this.frameOfDiscernment = frameOfDiscernment;
	}

	/**
	 * Returns true if the manager has all the field he needs set right, false
	 * otherwise
	 * 
	 * @return
	 */
	public boolean isVAlid() {
		if (this.monitoredServices != null && this.trustConfiguration != null
				&& frameOfDiscernment != null)
			return true;
		else
			return false;
	}

	/**
	 * Returns a list of the reputation obtained applying all the different
	 * {@link JointOperator}.
	 * 
	 * @param service
	 * @throws JointNotPossibleException
	 * @throws MassDistributionNotValidException
	 * @throws CloneNotSupportedException
	 * @throws NullSourcesException
	 */
	public ArrayList<JointMassDistribution> getAlltheReputations(Service service)
			throws MassDistributionNotValidException,
			JointNotPossibleException, CloneNotSupportedException,
			NullSourcesException {

		ReputationManager reputationManager = new ReputationManager(
				trustConfiguration, frameOfDiscernment);

		ArrayList<JointMassDistribution> allreputationMass = reputationManager
				.getAllJointMasses(service, allSources);

		return allreputationMass;

	}

	/**
	 * Returns the relationshipTrust between the caller and the callee
	 * 
	 * @param caller
	 * @param calle
	 * @return
	 */
	public MassDistribution getRelationship(Service caller, Service callee) {
		// compute the relationship mass
		MassDistribution monitoredMass;
		try {
			monitoredMass = RelationshipManager.getRelationshipTrust(
					(Service) caller.clone(), (Service) callee.clone(),
					trustConfiguration, frameOfDiscernment);
			return monitoredMass;
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}

	}

	/**
	 * @param reputation
	 * @param relationshiptrust
	 * @return
	 * @throws CloneNotSupportedException
	 * @throws DempsterTotalConflictException
	 */
	public MassDistribution getAggregateTrust(MassDistribution reputation,
			MassDistribution relationshiptrust)
			throws CloneNotSupportedException, DempsterTotalConflictException {
		if (reputation != null && relationshiptrust != null) {
			MassDistribution clonedReputation = (MassDistribution) reputation
					.clone();
			MassDistribution clonedRelationship = (MassDistribution) relationshiptrust
					.clone();
			MassDistribution aggregateMass = TrustMAnager.getAggregationTrust(
					clonedReputation, clonedRelationship, frameOfDiscernment);

			return aggregateMass;
		}
		return null;

	}
}
